/*
  Find min sub-string in string containing key words.

  Solution here has some problems (opportunities): 
  * only finding min distance of start of key words 
    (negating word length) 
  * could be building solution on input stream instead of waiting
  * no failure... 
*/

#include <iostream>
#include <algorithm>
#include <iterator>
#include <sstream>
#include <vector>
#include <list>

using namespace std;

string read_input() {
    ostringstream s;
    s << cin.rdbuf();
    return s.str();
}

typedef vector<string> Strings;
typedef vector< string::size_type > Positions;
typedef vector< Positions > ContainerPositions;
typedef pair< string::size_type, string::size_type > Range;
typedef vector< Positions::const_iterator > Possible;
typedef pair< Positions::const_iterator, Positions::const_iterator > ItPair;
typedef vector< ItPair > ItPairs;

bool less_than( const Range &a, const Range &b ) {
    return ( a.second - a.first ) < ( b.second - b.first );
}
ostream &operator<<( ostream &o, Range const &r ) {
    return o << "(" << r.first << "," << r.second << ")";
}

Possible next( ItPairs & its ) {
    Possible result;
    for ( ItPairs::const_iterator it( its.begin() ), end( its.end() );
	  end != it; it++ ) {
	if ( it->second != it->first ) {
	    result.push_back( it->first );
	}
    }
    return result;
}

Range findMinRange( ContainerPositions const & nPos ) {

    ItPairs its;
    for ( unsigned i =0; i< nPos.size(); i++ ) {
	its.push_back( ItPair( nPos[i].begin(), nPos[i].end()) );
    }
    
    Possible p( next( its ) );
    Range rmin(0,-1u);

    while ( p.size() == its.size() ) {
	unsigned min_i = 0;
	string::size_type min( *p.front() ), max( *p.front() );
	for ( Possible::const_iterator pit(p.begin()), pend(p.end());
	      pend != pit; pit++ ) {
	    if ( **pit > max ) { max = **pit; }
	    if ( **pit < min ) { min = **pit; min_i = pit-p.begin(); }
	}
	Range v( min, max );
	if ( less_than(v, rmin ) ) {
	    rmin = v;
	}
	its[min_i].first++;
	p = next( its );
    }
    return rmin;
}

int main( int argc, char *argv[] ) {

    Strings searches;
    copy( argv+1, argv+argc, back_insert_iterator<Strings>(searches) );
    const string input( read_input() );
    // cout << input;

    vector<Positions> locs;
    for ( Strings::const_iterator it(searches.begin()), end(searches.end()); 
	  end != it; it++ ) {
	locs.push_back(Positions());
	string::size_type pos(0);
	while ( input.npos != pos && ( pos < input.size() ) ) {
	    if ( input.npos != ( pos = input.find( *it, pos ) ) ) {
		locs.back().push_back( pos++ );
	    }
	}
    }

    Range r( findMinRange( locs ) );
    cout << r << endl;
    cout << "\"" << input.substr( r.first, r.second ) << "\"" << endl;

#if 0
    for ( vector<Positions>::const_iterator it(locs.begin()), end(locs.end()); 
	  end != it;
	  it++ ) {
	copy( it->begin(), it->end(), ostream_iterator<string::size_type>( cout, " " ) );
	cout << endl;
    }
#endif

    // for_each( locs.begin(), locs.end(), 

    return 0;
}
